import { h } from '@knno/dom/jsx';
import { Cell, CellProps } from './cell';
import { formatNumber } from '../editor/editor';

export type NumberCellProps = CellProps<NumberCell, NumberCellProps, number> & {
	precision?: number;
	prefix?: string;
	suffix?: string;
};

export class NumberCell extends Cell<NumberCell, NumberCellProps, number> {
	private static ALLOW_CHARACTERS = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '-'];
	private static ALLOW_CONTROLS = [
		'Backspace',
		'Delete',
		'Tab',
		'ArrowLeft',
		'ArrowRight',
		'ArrowUp',
		'ArrowDown',
		'Home',
		'End',
		'PageUp',
		'PageDown',
	];

	init() {
		this.addClass('number');
		const { precision = 0, readonly } = this.attrs;

		if (!readonly) {
			this.attr('contenteditable', 'true');
		}

		if (this.attrs.prefix) {
			this.attr('prefix', this.attrs.prefix);
		}

		if (this.attrs.suffix) {
			this.attr('suffix', this.attrs.suffix);
		}
		const v = this.getValue();
		if (v === null || isNaN(v)) {
			this.setValue(0, { noEvents: true });
		} else {
			this.text(formatNumber(this.getValue(), precision));
		}

		this.on('blur', () => this.handleBlur());
		this.on('keydown', (evt) => this.handleKeyDown(evt));
		this.on('input', () => this.handleInput());
	}

	private tidy(txt: string | null): number | null {
		if (txt === '' || txt === null) {
			return null;
		} else {
			let num = parseFloat(txt);
			if (isNaN(num)) {
				return null;
			} else {
				let precision = this.attrs.precision ?? 0;
				if (precision < 0) precision = 0;
				if (num > Number.MAX_SAFE_INTEGER) {
					num = Number.MAX_SAFE_INTEGER;
				}
				num = Math.round(num * 10 ** precision) / 10 ** precision;
				return num;
			}
		}
	}

	private handleBlur(): void {
		const value = this.getValue();
		if (value === null) {
			this.text('0');
			return;
		}
		const txt = formatNumber(value, this.attrs.precision ?? 0);
		this.text(txt);
	}

	private handleKeyDown(evt: KeyboardEvent): void {
		if (evt.ctrlKey) return;
		let backspaceOrDelete = false;
		if (NumberCell.ALLOW_CONTROLS.includes(evt.key)) {
			if (evt.key !== 'Backspace' && evt.key !== 'Delete') {
				return;
			}
			backspaceOrDelete = true;
		}
		evt.preventDefault();
		if (!NumberCell.ALLOW_CHARACTERS.includes(evt.key) && !backspaceOrDelete) {
			return;
		}
		const selection = getSelection();
		if (!selection) {
			return;
		}
		const range = selection.getRangeAt(0);
		if (!range) {
			return;
		}
		if (!range.collapsed) {
			range.deleteContents();
			if (range.startContainer === this.elems()[0]) {
				const textNode = document.createTextNode('');
				range.insertNode(textNode);
				range.selectNodeContents(textNode);
			}
			range.collapse();
			if (evt.key === 'Backspace' || evt.key === 'Delete') {
				this.setValue(this.tidy(this.elems()[0].textContent), { noUpdate: true });
				return;
			}
		}
		// 首先，需要获取当前光标位置，然后根据按键的类型，判断是插入字符还是删除字符。
		// 然后，需要判断小数点的限制，负号的限制，以及判断是退格还是删除（正确删除光标前还是光标后的字符）。
		// 最后，处理按键后光标的位置。
		const originStart = range.startOffset;
		if (evt.key === 'Backspace') {
			if (originStart === 0) {
				return;
			}
			range.setStart(range.startContainer, originStart - 1);
			range.setEnd(range.startContainer, originStart);
			range.deleteContents();
			range.collapse();
			this.setValue(this.tidy(this.elems()[0].textContent), { noUpdate: true });
			return;
		} else if (evt.key === 'Delete') {
			if (originStart === this.text().length) {
				return;
			}
			range.setStart(range.startContainer, originStart);
			range.setEnd(range.startContainer, originStart + 1);
			range.deleteContents();
			range.collapse();
			this.setValue(this.tidy(this.elems()[0].textContent), { noUpdate: true });
			return;
		} else {
			const precision = this.attrs.precision ?? 0;
			if ((evt.key === '.' && this.text().includes('.')) || precision < 1) {
				return;
			} else if (evt.key === '-' && originStart !== 0) {
				return;
			}
			// 如果光标位置在第一位，且第一位是负号，则不允许输入任何字符
			if (originStart === 0 && this.text().startsWith('-')) {
				return;
			}
			// 在光标位置插入字符
			const textNode = range.startContainer as Text;
			const text = textNode.textContent ?? '';
			let offset = range.startOffset;
			let newText = text.slice(0, offset) + evt.key + text.slice(offset);
			// 如果光标位置在小数点后，则限制小数点后的位数
			const dotIndex = newText.indexOf('.');
			if (dotIndex > 0 && newText.length - dotIndex > precision + 1) {
				newText = newText.slice(0, dotIndex + precision + 1);
			}
			textNode.textContent = newText;
			// 移动光标位置，如果光标位置超过了文本长度，则将光标位置设置为文本长度
			offset++;
			if (offset > newText.length) {
				offset = newText.length;
			}
			console.log(offset);
			range.setStart(textNode, offset);
			range.setEnd(textNode, offset);
			range.collapse();
			this.setValue(this.tidy(this.elems()[0].textContent), { noUpdate: true });
		}
	}

	private handleInput(): void {
		const txt = this.text().trim();
		if (txt === '-' || txt === '.') {
			this.setValue(0);
		} else {
			this.tidy(txt);
		}
	}

	protected update(): void {
		const v = this.getValue();
		const txt = formatNumber(v, this.attrs.precision ?? 0);
		this.text(txt);
	}
}
